Modeling
Conjoint Analysis

An Introduction to the Hierarchical Bayesian Multinominal Logit

Bowen Hickman and Marc Dotson

Conjoint

Predicting new product success

In order to predict new product success, you need to estimate product demand

  • New (hypothetical) products don’t exist and can’t be used in a test market
  • We can ask people their preferences, but stated preferences are unreliable
  • If people are bad at stating preferences, they’re good at making choices, so let’s us get at their revealed preferences
  • If you can estimate product demand as a function of product features and price, you can design a new product that you can expect to succeed

Conjoint analysis is a survey-based experiment for estimating product demand where product features and price are evaluated jointly (i.e., conjointly)

  • Products are defined by attributes, each with a number of levels
  • Respondents choose from among product alternatives
  • Respondent-level preferences are estimated for each attribute level
  • Preference estimates are used to make counterfactual predictions in a simulated market
  • Market simulators inform new product development, pricing, product line optimization, etc.

Multilevel Modeling

\[ \Large{U_{hj} = \beta_{h1}x_{j1} + \beta_{h2}x_{j2} + \cdots + \beta_{hk}x_{jk} + \epsilon_{hj}} \]

\[ \Large{\color{grey}{U_{hj} = \beta_{h1}\color{black}{x_{j1}} + \beta_{h2}\color{black}{x_{j2}} + \cdots + \beta_{hk}\color{black}{x_{jk}} + \epsilon_{hj}}} \]

\[ \Large{\color{grey}{U_{hj} = \color{black}{\beta_{h1}}x_{j1} + \color{black}{\beta_{h2}}x_{j2} + \cdots + \color{black}{\beta_{hk}}x_{jk} + \epsilon_{hj}}} \]

\[ \Large{\color{grey}{U_{hj} = \color{black}{\beta_{\color{red}{h}1}}x_{j1} + \color{black}{\beta_{\color{red}{h}2}}x_{j2} + \cdots + \color{black}{\beta_{\color{red}{h}k}}x_{jk} + \epsilon_{hj}}} \]

Complete pooling

Groups have the same parameters from one model

Partial pooling

Each group has their own parameters but they pool information in one model

No pooling

Each group has their own parameters from separate models

Multilevel logistic regression

\[ \large{y_{hj} \sim \text{Binomial}(1, p_{hj})} \\ \large{\log\left({p_{hj} \over 1 - p_{hj}}\right) = \beta_{h0} + \beta_{h1} x_{j1} + \cdots + \beta_{hp} x_{jp}} \]

  • The \(h\) index references the group that observation \(i\) belongs to
  • We can condition the intercept \(\beta_{h0}\), slopes \(\beta_{hp}\), or both by group
  • This allows us to capture heterogeneous effects across groups
  • Using Bayesian inference gives us adaptive regularization

Bayesian Inference

Frequentist

  • Data \(X, Y\) is a random variable
  • Parameter estimates are point estimates
  • Confidence intervals are a collection of theoretical point estimates

Bayesian

  • Parameters \(\beta\) are random variables
  • Parameter estimates are posterior distributions
  • Credible intervals are summaries of posterior distributions

Fitting Bayesian models with Bambi

import statsmodels.formula.api as smf
import bambi as bmb

# Fit a frequentist logistic regression
fr_fit = smf.glm(
  'y ~ x1 + x2 + x3', 
  data = conjoint_data,
  family = sm.families.Binomial()
).fit()

# Fit a Bayesian logistic regression
ba_fit = bmb.Model(
  'y ~ x1 + x2 + x3', 
  data = conjoint_data,
  family = 'bernoulli'
).fit()

So why fit a Bayesian model?

  • Incorporate prior information into your model
  • Quantify uncertainty directly in the form of a posterior distribution
  • Get adaptive regularization as part of a multilevel model

Multinomial Logit

Multinomial logit

\[ \large{y_{j} \sim \text{Multinomial}(n_{jk}, p_{jk})} \\ \large{\log\left({p_{jk} \over \sum_k p_{jk}}\right) = \beta_{0} + \beta_{1} x_{j1} + \cdots + \beta_{p} x_{jp}} \]

  • The multinomial logit is a generalization of logistic regression
  • Also referred to as multinomial logistic regression, multiclass logistic regression, and categorical regression
  • The outcome is a categorical variable with more than two categories

Fitting a multinomial logit with Bambi

# Fit a Bayesian multinomial logit
ba_fit = bmb.Model(
  'y ~ x1 + x2 + x3', 
  data = conjoint_data,
  family = 'categorical'
).fit()

Hierarchical Multinomial Logit

Hierarchical multinomial logit

\[ \large{y_{hj} \sim \text{Multinomial}(n_{jk}, p_{hjk})} \\ \large{\log\left({p_{hjk} \over \sum_k p_{hjk}}\right) = \beta_{h0} + \beta_{h1} x_{j1} + \cdots + \beta_{hp} x_{jp}} \]

  • A hierarchical model is a multilevel model where the outcomes are nested (e.g., choices nested within respondents)
  • The hierarchical multinomial logit (HMNL) is a generalization of hierarchical logistic regression
  • The outcome is a categorical variable with more than two categories where there are multiple outcomes per group (e.g., multiple choices per respondent)

Fitting an HMNL with Bambi

We can have all of our parameters vary by group (i.e., random effects)

# Fit a Bayesian hierarchical multinomial logit
ba_fit = bmb.Model(
  'y ~ (x1 + x2 + x3 | group)', 
  data = conjoint_data,
  family = 'categorical'
).fit()

Fitting an HMNL with Bambi

Or we can have some parameters vary by group and some not (i.e., mixed effects)

# Fit a Bayesian hierarchical multinomial logit
ba_fit = bmb.Model(
  'y ~ (1 | group) + x1 + x2 + x3', 
  data = conjoint_data,
  family = 'categorical'
).fit()